import 'dart:io';

import 'package:cgvc/basis/basis_refresh_list_view_model.dart';
import 'package:cgvc/basis/scroll_top_model.dart';
import 'package:cgvc/basis/view_state.dart';
import 'package:cgvc/helper/string_helper.dart';
import 'package:cgvc/view_model/theme_view_model.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';

//提供一个model的provider
class BasisProviderWidget<T extends ChangeNotifier> extends StatefulWidget {
  final ValueWidgetBuilder<T> builder;
  final T model;
  final Widget child;
  final Function(T) onModelReady;

  BasisProviderWidget(
      {Key key,
      @required this.builder,
      @required this.model,
      this.child,
      this.onModelReady})
      : super(key: key);

  @override
  _BasisProviderWidgetState<T> createState() {
    return _BasisProviderWidgetState<T>();
  }
}

class _BasisProviderWidgetState<T extends ChangeNotifier>
    extends State<BasisProviderWidget<T>> {
  T model;

  @override
  void initState() {
    model = widget.model;
    widget.onModelReady?.call(model);
    super.initState();
  }

  @override
  void dispose() {
    model?.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider<T>.value(
      value: model,
      child: Consumer<T>(
        builder: widget.builder,
        child: widget.child,
      ),
    );
  }
}

///封装成widget，提供两个model的provider
class BasisProviderWidget2<A extends ChangeNotifier, B extends ChangeNotifier>
    extends StatefulWidget {
  //为了传递给consumer2
  final Widget Function(BuildContext context, A model1, B model2, Widget child)
      builder;
  final A model1;
  final B model2;
  final Widget child;
  final Function(A, B) onModelReady;
  BasisProviderWidget2(
      {Key key,
      @required this.builder,
      @required this.model1,
      @required this.model2,
      this.child,
      this.onModelReady})
      : super(key: key);

  @override
  _BasisProviderWidgetState2<A, B> createState() {
    return _BasisProviderWidgetState2<A, B>();
  }
}

class _BasisProviderWidgetState2<A extends ChangeNotifier,
    B extends ChangeNotifier> extends State<BasisProviderWidget2<A, B>> {
  A model1;
  B model2;

  @override
  void initState() {
    this.model1 = widget.model1;
    this.model2 = widget.model2;
    widget.onModelReady?.call(model1, model2);
    super.initState();
  }

  @override
  void dispose() {
    this.model1?.dispose();
    this.model2?.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider<A>.value(value: model1),
        ChangeNotifierProvider<B>.value(value: model2),
      ],
      child: Consumer2<A, B>(
        builder: widget.builder,
        child: widget.child,
      ),
    );
  }
}

class BasisRefreshListProviderWidget<A extends BasisRefreshListViewModel,
    B extends ScrollTopModel> extends BasisProviderWidget2<A, B> {
  BasisRefreshListProviderWidget({
    Key key,
    @required
        Widget Function(BuildContext context, A model, int index) itemBuilder,
    @required A model1,
    @required B model2,
    Function(A, B) onModelReady,
    Function(BuildContext context, A model1, B model2, Widget child)
        loadingBuilder,
    Function(BuildContext context, A model1, B model2, Widget child)
        emptyBuilder,
    Function(BuildContext context, A model1, B model2, Widget child)
        errorBuilder,
    Widget child,
  }) : super(
          key: key,
          model1: model1,
          model2: model2 ?? ScrollTopModel(ScrollController(), height: 400),
          child: child,
          onModelReady: (model1, model2) {
            //加载数据
            model1.initData();

            //初始化滚动监听
            model2.initListener();

            //初始化完成回调
            onModelReady?.call(model1, model2);
          },
          builder: (context, model1, model2, child) {
            if (model1.loading) {
              return loadingBuilder != null
                  ? loadingBuilder(context, model1, model2, child)
                  : LoadingStateWidget();
            } else if (model1.empty) {
              return emptyBuilder != null
                  ? emptyBuilder(context, model1, model2, child)
                  : EmptyStateWidget(onPressed: () => 1);
            } else if (model1.error) {
              return errorBuilder != null
                  ? errorBuilder(context, model1, model2, child)
                  : ErrorStateWidget(
                      onPressed: () => model1.initData,
                      error: model1.viewStateError,
                    );
            }
            return Scaffold(
              body: SmartRefresher(
                enablePullDown: true,
                enablePullUp: true,
                header: Platform.isAndroid
                    ? MaterialClassicHeader(
                        backgroundColor: Colors.white,
                        color: ThemeViewModel.accentColor,
                      )
                    : ClassicHeader(),
                footer: SmartLoadMoreFooter(),
                onRefresh: model1.refresh,
                onLoading: model1.loadMore,
                controller: model1.refreshController,
                child: ListView.builder(
                  controller: model2.scrollController,
                  shrinkWrap: true,
                  itemCount: model1.list.length,
                  itemBuilder: (context, index) {
                    return itemBuilder(context, model1, index);
                  },
                ),
              ),
              floatingActionButton:
                  !model2.showTopBtn || ThemeViewModel.hideFloatingButton
                      ? null
                      : FloatingActionButton(
                          tooltip: StringHelper.getS().tooltipScrollTop,
                          child: Icon(
                            Icons.vertical_align_top,
                            color: Colors.white,
                          ),
                          onPressed: () => model2.scrollTo(),
                        ),
            );
          },
        );
}

class SmartLoadMoreFooter extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return CustomFooter(
        height: 50,
        builder: (BuildContext context, LoadStatus mode) {
          Widget body;
          if (mode == LoadStatus.idle) {
            body = Text(
              StringHelper.getS().loadIdle,
              textScaleFactor: ThemeViewModel.textScaleFactor,
              style: Theme.of(context).textTheme.caption,
            );
          } else if (mode == LoadStatus.loading) {
            body = CupertinoActivityIndicator();
          } else if (mode == LoadStatus.failed) {
            body = Text(
              StringHelper.getS().loadFailed,
              textScaleFactor: ThemeViewModel.textScaleFactor,
              style: Theme.of(context).textTheme.caption,
            );
          } else if (mode == LoadStatus.canLoading) {
            body = Text(
              StringHelper.getS().loadIdle,
              textScaleFactor: ThemeViewModel.textScaleFactor,
              style: Theme.of(context).textTheme.caption,
            );
          } else {
            body = Text(
              StringHelper.getS().loadNoMore,
              textScaleFactor: ThemeViewModel.textScaleFactor,
              style: Theme.of(context).textTheme.caption,
            );
          }
          return Container(
            height: 50,
            child: Center(
              child: body,
            ),
          );
        });
  }
}

class ErrorStateWidget extends StatelessWidget {
  final ViewStateError error;
  final String title;
  final String message;
  final Widget image;
  final Widget buttonText;
  final String buttonTextData;
  final VoidCallback onPressed;

  const ErrorStateWidget(
      {Key key,
      @required this.error,
      this.title,
      this.message,
      this.image,
      this.buttonText,
      this.buttonTextData,
      @required this.onPressed})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    var defaultImage;
    var defaultTitle;
    var errorMessage = error.message;
    String defaultTextData = StringHelper.getS().viewStateRetry;
    switch (error.errorType) {
      case ErrorType.network:
        defaultImage = const Icon(
          Icons.network_check,
          color: Colors.grey,
          size: 80,
        );
        defaultTitle = StringHelper.getS().viewStateNetworkError;
        errorMessage = '';
        break;
      case ErrorType.normal:
        defaultImage = const Icon(
          Icons.error,
          size: 80,
          color: Colors.grey,
        );
        defaultTitle = StringHelper.getS().viewStateError;
        break;
    }
    return ViewStateWidget(
      onPressed: onPressed,
      image: image ?? defaultImage,
      title: title ?? defaultTitle,
      message: message ?? errorMessage,
      buttonTextData: buttonTextData ?? defaultTextData,
      buttonText: buttonText,
    );
  }
}

class LoadingStateWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: ClipRRect(
        borderRadius: BorderRadius.circular(6),
        child: Container(
          color: Color(0x60000000),
          padding: EdgeInsets.all(20),
          child: CupertinoActivityIndicator(
            radius: 12,
          ),
        ),
      ),
    );
  }
}

class EmptyStateWidget extends StatelessWidget {
  final String message;
  final Widget image;
  final Widget buttonText;
  final VoidCallback onPressed;
  EmptyStateWidget(
      {Key key,
      this.image,
      this.buttonText,
      this.message,
      @required this.onPressed})
      : super(key: key);
  @override
  Widget build(BuildContext context) {
    return ViewStateWidget(
      onPressed: onPressed,
      image: image ??
          Icon(
            Icons.hourglass_empty,
            size: 100,
            color: Colors.grey,
          ),
      title: message ?? StringHelper.getS().viewStateEmpty,
      buttonText: buttonText,
      buttonTextData: StringHelper.getS().viewStateRefresh,
    );
  }
}

class ViewStateWidget extends StatelessWidget {
  final String title;
  final String message;
  final Widget image;
  final Widget buttonText;
  final String buttonTextData;
  final VoidCallback onPressed;

  ViewStateWidget({
    Key key,
    this.title,
    this.image,
    this.message,
    this.buttonText,
    @required this.onPressed,
    this.buttonTextData,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    var titleStyle = Theme.of(context).textTheme.subhead.copyWith(
          color: Colors.grey,
          fontSize: 14,
        );
    var messageStyle = titleStyle.copyWith(
      color: titleStyle.color.withOpacity(0.7),
      fontSize: 14,
    );
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      crossAxisAlignment: CrossAxisAlignment.center,
      children: <Widget>[
        image ??
            Icon(
              Icons.error,
              size: 80,
              color: Colors.grey[500],
            ),
        Padding(
          padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 0),
          child: Column(
            mainAxisSize: MainAxisSize.max,
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Text(
                title ?? StringHelper.getS().viewStateError,
                style: titleStyle,
                textScaleFactor: ThemeViewModel.textScaleFactor,
              ),
              SizedBox(
                height: 12,
              ),
              ConstrainedBox(
                constraints: BoxConstraints(
                  maxHeight: 200,
                  minHeight: message != null ? 10 : 0,
                ),
                child: SingleChildScrollView(
                  child: Text(
                    message ?? '',
                    style: messageStyle,
                    textScaleFactor: ThemeViewModel.textScaleFactor,
                  ),
                ),
              ),
              Center(
                child: ViewStateButton(
                  child: buttonText,
                  textData: buttonTextData,
                  onPressed: onPressed,
                ),
              ),
            ],
          ),
        ),
      ],
    );
  }
}

//公用button
class ViewStateButton extends StatelessWidget {
  final String textData;
  final Widget child;
  final VoidCallback onPressed;
  const ViewStateButton({@required this.onPressed, this.child, this.textData})
      : assert(child == null || textData == null);
  @override
  Widget build(BuildContext context) {
    return OutlineButton(
      child: child ??
          Text(
            textData ?? StringHelper.getS().viewStateRetry,
            textScaleFactor: ThemeViewModel.textScaleFactor,
            style: Theme.of(context).textTheme.caption.copyWith(fontSize: 14),
          ),
      textColor: Colors.grey,
      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(6)),
      splashColor: Theme.of(context).splashColor,
      onPressed: onPressed,
      highlightedBorderColor: Theme.of(context).splashColor,
    );
  }
}
